package org.reliablesource.prism.ui.actions;

/**
 *  
 *  Copyright (c) 2006, Reliable Source, Inc. All Rights Reserved
 *
 *	Created on: Mar 15, 2006
 *  @author Dennis Park <a href="mailto:dennis.park@gmail.com">dennis.park@gmail.com</a>
 *
 */

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PlatformUI;
import org.reliablesource.prism.core.IPrismScreen;
import org.reliablesource.prism.core.IPrismTutorial;
import org.reliablesource.prism.core.plugin.PrismCorePlugin;
import org.reliablesource.prism.ui.composite.ViewMediator;
import org.reliablesource.prism.ui.plugin.PrismPlugin;
import org.reliablesource.prism.ui.util.PrismUIConstants;

/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class CopyOfWorkingCaptureScreenAction implements IWorkbenchWindowActionDelegate, IPropertyChangeListener {
//	private IWorkbenchWindow window;
	private Listener captureRequestListener;

	// default the capture to happen on middle button click
	int USE_BUTTON = PrismUIConstants.MOUSE_MIDDLE;

	private static String DIRECTORY_PREF;

	Display display;

	/**
	 * The constructor.
	 */
	public CopyOfWorkingCaptureScreenAction() {
		display = PlatformUI.getWorkbench().getDisplay();
		//	Create the wb event listener
		//		NOTE:	Menu event life-cycle:  ARM->SHOW->HIDE->SELECTION

		captureRequestListener = new Listener() {

			public void handleEvent(final Event event) {
				display = Display.getDefault();
				
				display.sleep();
				display.sleep();
				
				while(display.readAndDispatch());
				while(display.readAndDispatch());
				display.sleep();
				while(display.readAndDispatch());
				while(display.readAndDispatch());

				if (event.type == SWT.MenuDetect) 
					System.err.println("SWT.MenuDetect");
//				 else if (event.type == SWT.FocusIn) 
//					System.err.println("FocusIn called");
//				 else if (event.type == SWT.Activate) 
//					System.err.println("Activate called");
				 else if (event.type == SWT.Arm)
					System.err.println("SWT.Arm");
				 else if (event.type == SWT.Show) 
					System.err.println("SWT.Show");
				 else if (event.type == SWT.Selection) 
					System.err.println("SWT.Selection");
				 else if (event.type == SWT.Hide) 
					System.err.println("SWT.Hide");

				else if (event.type == SWT.MouseDown
						&& event.button == USE_BUTTON
//						&& !PrismPlugin.getDefault().isCapturePressed()
						) {
//					PrismPlugin.getDefault().setCapturePressed(true);
					System.err.println("SWT.MouseDown: " + event.button);
				} else if (event.type == SWT.MouseUp
						&& event.button == USE_BUTTON
//						&& PrismPlugin.getDefault().isCapturePressed()
						) {
//					PrismPlugin.getDefault().setCapturePressed(false);
					System.err.println("SWT.MouseUp : " + event.button);

					
					final IPrismScreen screen = PrismCorePlugin.getDefault().getElementFactory().createScreen();

					// FIXME: fileType and fileName should be decided
					// by user prefs.
					final String fileType = "jpg";
					final String fileName = "TPv001_"
							+ System.currentTimeMillis();

					// Initialize the created instance.
					
					screen.setPointerStart(new Point(event.x, event.y));
					screen.setName(fileName);
					screen.setImageFileType(fileType);
					screen.setImageFilePath(DIRECTORY_PREF);

					Rectangle area;

					//	Screen shot scope set to Workbench
					area = display.getActiveShell().getBounds();

					//  Screen shot scope set to entire display
					//					area = display.getBounds();

					final Image image = new Image(display, area);

					/* Take the screen shot */
					GC gc = new GC(display);
					gc.copyArea(image, area.x, area.y);

					//	FIXME :	Embed a watermark
					//gc.drawText("Reliable Source, Inc. - Dennis Park", area.x/3, area.y/2);					
					gc.dispose();

					PrismPlugin.getDefault().addImage(fileName.trim(),ImageDescriptor.createFromImageData(image.getImageData()));
					
					image.dispose();
					
					System.err.println("Saving screen capture...");		
					
					PrismPlugin.getDefault().saveSWTImage(
							PrismPlugin.getDefault().readScreen(screen).getImageData(),
									DIRECTORY_PREF
									+ fileName.trim(), fileType);	
					
					System.err.println("Save finished successfully..."
							+ DIRECTORY_PREF);
					
					ViewMediator.getInstance().showNewImage(screen);
					int nImages = ((IPrismTutorial) PrismCorePlugin.getDefault()
							.getModel().getChild(0)).getChildListSize();
					//	Notify clients that are interested in this model
					//		change.
					
//					((Observable)PrismCorePlugin.getDefault().getModel()).setChanged();

					
					//	Fork a new thread that will save this to the fileSystem.
					Thread saveThread = new Thread() {
						public void run() {
							final List changeList = new ArrayList();
							changeList.add(PrismUIConstants.ADD_SCREEN_ELT);
							changeList.add(screen);
							changeList.add(screen.getParent());
							display.asyncExec(new Runnable(){
								public void run(){
									((Observable)PrismCorePlugin.getDefault().getModel()).notifyObservers(changeList);									
								}
							});

						}
					};
				
					System.err.println("Image captured..." + nImages
							+ " captured so far.");
//					event.doit = false;
				}
				
				display.sleep();
				
				if(!(event.type == SWT.FocusIn || event.type == SWT.FocusOut))
					display.getActiveShell().update();
				
//				while(display.readAndDispatch());
//				display.sleep();
//				while(display.readAndDispatch());
			}
		};

		
	}

	/**
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		
		Display d  = Display.getDefault();
		Shell [] shells = d.getShells();

		int nShells = shells.length;
		StringBuffer buffer = new StringBuffer();		
		for(int i =0; i < nShells; i++){
			System.err.println("Shell " + i );
			PrismPlugin.getDefault().printCompositeContext(shells[i], buffer);
		}
		if (action.isChecked()) {
			display.addFilter(SWT.MouseDown, captureRequestListener);
			display.addFilter(SWT.MouseUp, captureRequestListener);
			display.addFilter(SWT.MenuDetect, captureRequestListener);
			display.addFilter(SWT.Arm, captureRequestListener);
			display.addFilter(SWT.Show, captureRequestListener);
			display.addFilter(SWT.Selection, captureRequestListener);
			display.addFilter(SWT.Hide, captureRequestListener);
//			display.addFilter(SWT.Activate, captureRequestListener);
			display.addFilter(SWT.FocusIn, captureRequestListener);
			display.addFilter(SWT.FocusOut, captureRequestListener);
			
//			display.getShells()[0].addListener(SWT.MouseDown, captureRequestListener);
//			display.getShells()[0].addListener(SWT.MouseUp, captureRequestListener);
//			display.getShells()[0].addListener(SWT.MenuDetect, captureRequestListener);
//			display.getShells()[0].addListener(SWT.Arm, captureRequestListener);
//			display.getShells()[0].addListener(SWT.Show, captureRequestListener);
//			display.getShells()[0].addListener(SWT.Selection, captureRequestListener);
//			display.getShells()[0].addListener(SWT.Hide, captureRequestListener);
//			display.getShells()[0].addListener(SWT.Activate, captureRequestListener);
//			display.getShells()[0].addListener(SWT.FocusIn, captureRequestListener);
//			display.getShells()[0].addListener(SWT.FocusOut, captureRequestListener);
			
		} else {
			display.removeFilter(SWT.MouseDown, captureRequestListener);
			display.removeFilter(SWT.MouseUp, captureRequestListener);
			display.removeFilter(SWT.MenuDetect, captureRequestListener);
			display.removeFilter(SWT.Arm, captureRequestListener);
			display.removeFilter(SWT.Show, captureRequestListener);
			display.removeFilter(SWT.Selection, captureRequestListener);
			display.removeFilter(SWT.Hide, captureRequestListener);
//			display.removeFilter(SWT.Activate, captureRequestListener);
			display.removeFilter(SWT.FocusIn, captureRequestListener);
			display.removeFilter(SWT.FocusOut, captureRequestListener);
		}
	}

	private void readPrefrences() {

		//	Capture trigger setting
		String mouseButtonPref = PrismPlugin.getDefault()
				.getPreferenceStore().getString(PrismUIConstants.P_CAPTURE_TRIGGER);

		//	FIXME:	Problematic if user tries to deactivate a capture session?
		if (mouseButtonPref.equals(Integer.toString(PrismUIConstants.MOUSE_LEFT)))
			USE_BUTTON = PrismUIConstants.MOUSE_LEFT;
		if (mouseButtonPref.equals(Integer.toString(PrismUIConstants.MOUSE_MIDDLE)))
			USE_BUTTON = PrismUIConstants.MOUSE_MIDDLE;
		if (mouseButtonPref.equals(Integer.toString(PrismUIConstants.MOUSE_RIGHT)))
			USE_BUTTON = PrismUIConstants.MOUSE_RIGHT;

			StringBuffer buffer = new StringBuffer();
			String _savePath = PrismPlugin.getDefault().getPreferenceStore().getString(PrismUIConstants.P_PATH);
			
			if(_savePath.length() > 0)
				buffer.append(_savePath);
			
			buffer.append((_savePath.endsWith("/") || _savePath
					.endsWith("\\")) ? "" : PrismUIConstants.FILE_SEPERATOR);

			DIRECTORY_PREF = buffer.toString().trim();
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}

	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
		if (captureRequestListener == null)
			return;

		display.removeFilter(SWT.MouseDown, captureRequestListener);
		display.removeFilter(SWT.MouseUp, captureRequestListener);
		display.removeFilter(SWT.MenuDetect, captureRequestListener);
		display.removeFilter(SWT.Arm, captureRequestListener);
		display.removeFilter(SWT.Show, captureRequestListener);
		display.removeFilter(SWT.Selection, captureRequestListener);
		display.removeFilter(SWT.Hide, captureRequestListener);
		display.removeFilter(SWT.Activate, captureRequestListener);
		display.removeFilter(SWT.FocusIn, captureRequestListener);
		display.removeFilter(SWT.FocusOut, captureRequestListener);
		
		PrismPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(this);
	}

	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow _window) {
		PrismPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(this);
		readPrefrences();
	}

	public void propertyChange(PropertyChangeEvent _event) {
		if( _event.getProperty().equals(PrismUIConstants.P_PATH) ||
				_event.getProperty().equals(PrismUIConstants.P_CAPTURE_TRIGGER) )
				readPrefrences();
	}
}